/* Read yaal/LICENSE.md file for copyright and licensing information. */

#ifndef YAAL_TOOLS_SIGHAND_HXX_INCLUDED
#define YAAL_TOOLS_SIGHAND_HXX_INCLUDED 1

#include "hcore/hpointer.hxx"
#include "hcore/hchunk.hxx"
#include "hcore/hmultimap.hxx"
#include "hcore/hlist.hxx"
#include "hcore/hthread.hxx"
#include "hcore/hsingleton.hxx"

namespace yaal {

namespace tools {

/*! \brief Posix signal manager.
 *
 * Instance of HSignalService class is a global object that handles
 * dispatching of operating system level signals.
 */
class M_YAAL_TOOLS_PUBLIC_API HSignalService : public yaal::hcore::HSingleton<HSignalService> {
public:
	typedef yaal::hcore::HSingleton<HSignalService> base_type;
	typedef HSignalService this_type;
	typedef int (*raw_handler_t)( int );
	typedef yaal::hcore::HBoundCall<int ( int )> handler_t;
	typedef yaal::hcore::HPair<handler_t, void const*> handler_info_t;
private:
	typedef yaal::hcore::HMultiMap<int, handler_info_t> handlers_t;
	typedef handlers_t::value_list_t handler_list_t;
	typedef handlers_t::value_list_ptr_t handler_list_ptr_t;
	static int _exitStatus;
	bool _loop;
	yaal::hcore::HChunk _catch;
	yaal::hcore::HMutex _mutex;
	handlers_t _handlers;
public:
	static int _killGracePeriod;
	void register_handler( int, handler_t, void const* = nullptr );
	void call_handler( int );
	void flush_handlers( void const* );
	void reset_signal( int );
	void stop( void	);
	static int life_time( int );
private:
	HSignalService( void );
	~HSignalService( void );
	void run( void );
	bool want_restart( void ) const;
	void catch_signal( int );
	void block_signal( int );
	void schedule_exit( int );
	static void exit( int ) __attribute__(( __noreturn__ ));
	friend class yaal::hcore::HSingleton<HSignalService>;
	friend class yaal::hcore::HDestructor<HSignalService>;
};

/*! \brief Exception generated by HSignalService.
 */
typedef yaal::hcore::HExceptionT<HSignalService> HSignalServiceException;

}

}

#endif /* #ifndef YAAL_TOOLS_SIGHAND_HXX_INCLUDED */

